import store from '@/store/index.js';
import {
  checkType,
  isEmpty,
  jsonParse,
  queryStringify
} from "@/common/util.js";
/**
 * @description 根据不同service返回不同的报文字段, 处理接口返回的数据 baseUrl：访问资管后端返回的数据字段，ipayMobileView：访问商服后端返回的字段
 */
const returnMap = {
  ipayMobileView: {
    codeVal: '00',
    msgKey: 'msg',
    codeKey: 'code'
  }
}
/**
 * @description 获取请求头
 * @param {Object} congfigHeader api接口传的自定义头部信息
 * @returns {Object} 请求头
 */
function getHttpHeader(congfigHeader, service = "baseUrl") {
  const headerConfig = {
    ipayMobileView: {
      'Content-Type': 'application/json', // 默认application/json 还可选 application/x-www-form-urlencoded 数据转换为 query string。
      'X-GW-APP-ID': '1004',
      'X-GW-APP-MAIN-ID': '1004'
    },
    iassbff: {
      'Content-Type': 'application/json', // 默认application/json 还可选 application/x-www-form-urlencoded 数据转换为 query string。
    }
  }
  return Object.assign(headerConfig[service], congfigHeader);
}
/**
 * @description 小程序通用请求api;详细信息文档 参照 https://uniapp.dcloud.net.cn/api/request/network-file.html
 * @param {String} url 请求接口
 * @param {Object} data 请求参数
 * @param {Object} config 请求配置参数，例如config.loading 控制是否loading效果，header 配置请求头
 */
export function http(url = '', data = {}, config = {}) {
  let {
    method = 'POST', // 或 GET
      header = {}, // 配置请求头
      dataType = 'json', // 如果设为 json，会对返回的数据进行一次 JSON.parse，非 json 不会进行 JSON.parse
      responseType = 'text', // 设置响应的数据类型。合法值：text、arraybuffer
      timeout = 10000,
      title = "加载中", // loading提示语
      mask = true, // 控制loading遮罩
      loading = true, // 控制是否loading效果
      service = 'iassbff',
      goError = true, // 非正常返回，是否跳转到异常页面
  } = config;
  url = `${store.getters.configInfo[service]}${url}`;
  header = getHttpHeader(header, service);
  if (loading) uni.showLoading({
    title,
    mask
  });
  console.log('请求拦截：' + url, data)
  return new Promise((resolve, reject, defaults) => {
    uni.request({
      url,
      data,
      method,
      header,
      dataType,
      // #ifdef MP-WEIXIN
      responseType,
      // #endif
      timeout,
      success: (res) => {
        if (res.statusCode === 200 && responseType == 'arraybuffer') {
          resolve(res.data)
        } else {
          successHandle(res, service, resolve, reject, goError)
        }
      },
      fail: (err) => {
        errorHandle(err.errMsg, err)
      },
      complete: () => {
        if (loading) uni.hideLoading()
      }
    })
  })
}

/**
 * @description 小程序上传文件请求api;详细信息文档 参照 https://uniapp.dcloud.net.cn/api/request/network-file.html
 * @param {String} url 请求接口
 * @param {Object} data 上传文件及请求参数
 * @param {Object} config 请求配置参数，例如config.loading 控制是否loading效果，header 配置请求头
 */
export function upload(url = '', data = {}, config = {}) {
  let {
    // 注意微信小程序只支持单文件上传，传多个文件需要反复调用本API
    // files 为对象数组，例如[{name:"String	(multipart 提交时，表单的项目名，默认为 file)",uri:"String(文件的本地地址)"}]
    files = [], //files和filePath选其一, 需要上传的文件列表。使用 files 时，filePath 和 name 不生效。
      filePath = "", // files和filePath选其一,要上传文件资源的路径。
      name = 'file', // 文件对应的 key , 开发者在服务器端通过这个 key 可以获取到文件二进制内容
      formData = {} // HTTP 请求中其他额外的 form data
  } = data;
  let {
    title = "上传中",
      mask = true,
      loading = true,
      header = {}, // HTTP 请求 Header, header 中不能设置 Referer。
      timeout = 10000, //超时时间，单位 ms
      service = 'iassbff',
      goError = true, // 非正常返回，是否跳转到异常页面
  } = config;
  url = `${store.getters.configInfo[service]}${url}`;
  header = getHttpHeader({
    'Content-Type': 'multipart/form-data',
    ...header
  }, service)
  if (loading) uni.showLoading({
    title,
    mask
  });
  console.log('请求拦截：' + url, data)
  return new Promise((resolve, reject, defaults) => {
    uni.uploadFile({
      url,
      files,
      filePath,
      name,
      formData,
      timeout,
      header,
      success: (res) => {
        successHandle(res, service, resolve, reject, goError)
      },
      fail: (err) => {
        errorHandle(err.errMsg, err)
      },
      complete: () => {
        if (loading) uni.hideLoading()
      }
    });
  })
}

export function download(url = '', data = {}, config = {}) {
  let {
    title = "下载中",
      mask = true,
      loading = true,
      filePath = '', //指定文件下载后存储的路径 (本地路径)
      header = {}, // HTTP 请求 Header, header 中不能设置 Referer。
      timeout = 10000, //超时时间，单位 ms
      service = 'iassbff'
  } = config;
  url = url.indexOf('http') >= 0 ? `${url}${queryStringify(data)}` :
    `${store.getters.configInfo[service]}${url}${queryStringify(data)}`;
  header = getHttpHeader({
    'Content-Type': 'application/x-www-form-urlencoded',
    ...header
  }, service)
  if (loading) uni.showLoading({
    title,
    mask
  });
  console.log('请求拦截：' + url, data)
  return new Promise((resolve, reject, defaults) => {
    uni.downloadFile({
      url,
      filePath,
      timeout,
      header,
      success: (res) => {
        if (res.statusCode === 200) {
          resolve(res)
        } else {
          errorHandle()
        }
      },
      fail: (err) => {
        errorHandle(err.errMsg, err)
      },
      complete: () => {
        if (loading) uni.hideLoading()
      }
    });
  })
}

/**
 * @description 请求返回信息及状态码统一处理
 * @param {Object} res api接口返回数据 
 * @param {Function} resolve Promise.resolve 方法
 * @param {Function} reject Promise.reject 方法
 */
function successHandle(res = {}, service = 'iassbff', resolve, reject, goError) {
  if (res.statusCode === 200) {
    let data = checkType(res.data) === "object" ? res.data : jsonParse(res.data);
    console.log('响应拦截：', data)
    if (checkType(data) === "object") {
      if (service === 'iassbff') {
        if (data.respCode == "000000") {
          resolve(data.data);
        } else {
          if (goError) {
            errorHandle(data.respMsg)
          } else {
            reject(data)
          }
        }
      } else {
        let head = data.head || {};
        if (head.H_STATUS === '000000') { // 网关访问正常，网关状态码 00000 为这正常
          let body = data.body || {},
            returnConfig = returnMap[service];
          if (body[returnConfig.codeKey] == returnConfig.codeVal) { // 根据不同service取不同的报文字段，相等为请求正常
            resolve(body.data)
          } else {
            reject(body) // 根据不同service取不同的报文字段，异常信息在具体请求函数的 catch 里处理
          }
        } else {
          errorHandle(head.H_MSG) // 统一提示网关异常信息 head.H_MSG
        }
      }
    } else {
      errorHandle(`系统异常(${data && data.toString()})，请稍后再试!`)
    }
  } else {
    errorHandle(`请求失败(${res.statusCode})，请稍后再试！`)
  }
}
/**
 * @description 请求异常信息提示
 * @param {String} content 异常信息
 * @param {Object} errRes 异常信息数据
 */
export function errorHandle(content = '', errRes = {}) {
  content = content || '`系统异常，请稍后再试!`'
  uni.redirectTo({
    url: '/pages/iassCashier/error?errMsg=' + content,
  })
}